package com.taoist_awei.blog.infrastructure.service;

import com.taoist_awei.blog.core.JwtService;
import com.taoist_awei.blog.core.UserEntity;
import com.taoist_awei.blog.core.UserLoginService;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
/**
 * @author 高威
 * token生产工具类
 */
@Component
public class DefaultJwtService implements JwtService {

    private String secret;
    private int sessionTime;
    private UserLoginService loginService;


    @Autowired
    public DefaultJwtService(@Value("${jwt.secret}") String secret,
                             @Value("${jwt.sessionTime}") int sessionTime,
                             UserLoginService loginService) {
        this.secret = secret;
        this.sessionTime = sessionTime;
        this.loginService = loginService;
    }



    @Override
    public String toToken(UserEntity user) {
        String token = Jwts.builder()
                .setSubject(user.getUserId())
                .setExpiration(expireTimeFromNow())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
        loginService.login(user.getUserId(), token);
        return token;
    }

    private Date expireTimeFromNow() {
        return new Date(System.currentTimeMillis() * 1000 + sessionTime);
    }

    private void logout(String token) {
        Map<String, String> loginMap = loginService.getLoginMap();
        loginMap.forEach((key, value) -> {
            if (value.equals(token)) {
                loginMap.remove(key);
            }
        });
    }

    @Override
    public Optional<String> getSubFromToken(String token) {
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
            return Optional.ofNullable(claimsJws.getBody().getSubject());
        } catch (ExpiredJwtException e) {
            logout(token);
            return Optional.empty();
        } catch (Exception e) {
            return Optional.empty();
        }
    }
}